package com.itmk.HeHeXinXiApi.component;

import cn.hutool.json.JSONUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@Component
@ServerEndpoint(value = "/webSocket")//暴露ws服务应用路径
public class WebSocketService {
    private static final Logger log = LoggerFactory.getLogger(WebSocketService.class);

//    记录当前在线连接数
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
       * 连接建立成功调用的方法
    */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessionMap.put(username,session);
        log.info("有新用户加入.username={},当前在线人数为：{}",username,sessionMap.size());
        JSONObject result =new JSONObject();
        JSONArray array = new JSONArray();
        result.put("user",array);
        for (Object key :sessionMap.keySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username",key);
            array.put(jsonObject);
        }
        sendAllMessage(JSONUtil.toJsonStr(result));//发送给所有的客户端
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("username") String username){
        sessionMap.remove(username);
        log.info("有一连接关闭，移除username={}的用户session，当前在线人数为：{}",username,sessionMap.size());
    }

    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发过来的消息
     *
     * @param message 客户端发来的消息
     */
    @OnMessage
    public void onMessage(String message,Session session, @PathParam("username") String username){
        log.info("服务端收到用户username={}的消息",username,message);
        JSONObject obj = JSONUtil.parseObj(message);
        String toUsername = obj.getStr("to");//to表示发给哪个用户
        String text = obj.getStr("text");//发送的消息文本
        Session toSession = sessionMap.get(toUsername);//根据 to用户来获取 session. 再通过session发送文本消息
        if(toSession != null) {
            //服务器端 再把消息组装一下，组装后的消息包含发送人和发送的文本内容
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("from",username);
            jsonObject.put("text",text);
            this.sendMessage(jsonObject.toString(),toSession);
            log.info("发送给用户username={},消息。{}",toUsername,jsonObject.toString());
        }else {
            log.info("发送失败,未找到用户usrname={}的session",toUsername);
        }
    }

    @OnError
    public void onError(Session session, Throwable error){
        log.error("发生错误");
        error.printStackTrace();
    }



    /**
     * 服务器器发送消息给客户端
     */
    private void sendMessage(String message,Session toSession) {
        try {
            log.info("服务器给客户端[{}]发送消息{}",toSession.getId(),message);
            toSession.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("服务端发消息给客户端失败",e);
        }
    }

    /**
     * 服务器器发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()){
                log.info("服务器给客户端[{}]发送消息{}",session.getId(),message);
                session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            log.error("服务端发消息给客户端失败",e);
        }
    }

}
